﻿<#
.SYNOPSIS

This script creates partitions on any physical disks that have none.
#>

Set-StrictMode -Version "2.0"

function Get-NextAvailableDriveLetter ([char]$startLetter = 'C', [char]$endLetter = 'Z')
{
    $nextFreeLetter = $null
    
    [char[]]$possibleLetters = (([int]$startLetter)..([int]$endLetter))
    if ($endLetter -gt $startLetter)
    {
        $startLetter = $startLetter | Sort-Object -Descending
    }

    for ([int]$i = 0; $i -lt $possibleLetters.Length; $i++)
    {
        $d = New-Object -TypeName System.IO.DriveInfo -ArgumentList $possibleLetters[$i]
        if ($d.DriveType -eq [IO.DriveType]::NoRootDirectory)
        {
            $nextFreeLetter = $possibleLetters[$i]
            break
        }
    }
    return $nextFreeLetter
}


# Get a collection of the physical drives.
$diskDrives = Get-WmiObject "Win32_DiskDrive"

# Use diskpart to bring the disks online.
foreach($drv in $diskDrives)
{
    Write-Host ("Checking physical disk with index {0}" -f $drv.Index)
       
    [string]$diskPartPath = Join-Path ([System.Environment]::GetFolderPath(([System.Environment+SpecialFolder]::System))) "diskpart.exe"

    if (Test-Path $diskPartPath)
    {        
        [System.Diagnostics.ProcessStartInfo]$startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $diskPartPath
        $startInfo.CreateNoWindow = $false
        $startInfo.RedirectStandardInput = $true
        $startInfo.RedirectStandardOutput = $true
        $startInfo.UseShellExecute = $false
        $startInfo.WindowStyle = ([System.Diagnostics.ProcessWindowStyle]::Minimized)
        
        [System.Diagnostics.Process]$proc = [System.Diagnostics.Process]::Start($startInfo)
        $proc.StandardInput.WriteLine("SEL DISK {0}" -f $drv.Index)
        $proc.StandardInput.WriteLine("ONLINE DISK")
        $proc.StandardInput.WriteLine("RESCAN")
        $proc.StandardInput.WriteLine("EXIT")
        $proc.StandardInput.Close()
        $proc.WaitForExit()
    }
    else
    {
        Write-Host ("`tERROR: Unable to locate DiskPart ({0})" -f $diskPartPath) -ForegroundColor Red
    }
}

# Get a collection of the physical drives.
$diskDrives = Get-WmiObject "Win32_DiskDrive"

# For each physical drive, make sure there is at least one partition.
# If no partitions can be found for a given disk, use DiskPart to create
# an NTFS partition that spans the entire disk.
foreach($drv in $diskDrives)
{
    Write-Host ("Checking physical disk with index {0}" -f $drv.Index)
        
    if ((Get-WmiObject -Class "Win32_DiskPartition" -Filter ("DiskIndex = {0}" -f $drv.Index)) -eq $null)
    {
        Write-Host "`tNo partitions found for this physical disk."
        
        [string]$diskPartPath = Join-Path ([System.Environment]::GetFolderPath(([System.Environment+SpecialFolder]::System))) "diskpart.exe"
        
        if (Test-Path $diskPartPath)
        {        
            [System.Diagnostics.ProcessStartInfo]$startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $diskPartPath
            $startInfo.CreateNoWindow = $false
            $startInfo.RedirectStandardInput = $true
            $startInfo.RedirectStandardOutput = $true
            $startInfo.UseShellExecute = $false
            $startInfo.WindowStyle = ([System.Diagnostics.ProcessWindowStyle]::Minimized)
            
            [System.Diagnostics.Process]$proc = [System.Diagnostics.Process]::Start($startInfo)
            $proc.StandardInput.WriteLine("SEL DISK {0}" -f $drv.Index)
            $proc.StandardInput.WriteLine("ATTRIBUTES DISK CLEAR READONLY")
            $proc.StandardInput.WriteLine("ONLINE DISK")
            $proc.StandardInput.WriteLine("CRE PART PRI")
            $proc.StandardInput.WriteLine("SEL PART 1")
            $proc.StandardInput.WriteLine("FORMAT FS=NTFS QUICK")
            <# $proc.StandardInput.WriteLine("ASSIGN") #>
            $proc.StandardInput.WriteLine(("ASSIGN LETTER={0}" -f (Get-NextAvailableDriveLetter)))
            $proc.StandardInput.WriteLine("RESCAN")
            $proc.StandardInput.WriteLine("EXIT")
            $proc.StandardInput.Close()
            $proc.WaitForExit()
        }
        else
        {
            Write-Host ("`tERROR: Unable to locate DiskPart ({0})" -f $diskPartPath) -ForegroundColor Red
        }
    }
}

# Return a success error code.
exit 0